/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package desarrollosoft.ghce.vista.implementaciones;

import desarrollosoft.ghce.entidades.GrupoEtario;
import desarrollosoft.ghce.entidades.Sexo;
import desarrollosoft.ghce.servicio.interfaces.IServicioEstadisticas;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.zkoss.chart.model.CategoryModel;
import org.zkoss.chart.model.DefaultCategoryModel;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.select.SelectorComposer;
import org.zkoss.zk.ui.select.annotation.Listen;
import org.zkoss.zk.ui.select.annotation.VariableResolver;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zk.ui.select.annotation.WireVariable;
import org.zkoss.zul.Combobox;
import org.zkoss.zul.ListModelList;
import org.zkoss.zul.Messagebox;
import org.zkoss.zul.Window;

/**
 *
 * @author ariel
 */
@VariableResolver(org.zkoss.zkplus.spring.DelegatingVariableResolver.class)
public class ControladoraIndiceMortalidad extends SelectorComposer<Window> {
    
    @WireVariable("servicioEstadisticas")
    private IServicioEstadisticas servicioEstadisticas;
    
    @Wire
    private Combobox comboboxSexo;
    
    /*@Wire
    private Combobox comboboxEdadDesde;
    
    @Wire
    private Combobox comboboxEdadHasta;*/
    
    @Wire
    private Combobox comboboxGrupoEtario;
    
    @Wire
    private Combobox comboboxAnioDesde;
    
    @Wire
    private Combobox comboboxAnioHasta;
    
    @Wire
    private Combobox comboboxMesDesde;
    
    @Wire
    private Combobox comboboxMesHasta;
    
    @Wire
    private Window ventanaDetalles;
    
    private Window ventanaAnterior;
    
    private List<Sexo> listaSexos;
    //private List<String> listaEdades;
    private List<GrupoEtario> listaGruposEtarios;
    private List<String> listaAnios;
    private List<String> listaMeses;
    
    @Override
    public void doAfterCompose(Window comp) throws Exception {
        hacerAntesDeDibujar();
        super.doAfterCompose(comp);
        hacerDespuesDeDibujar();
    }
    
    private void hacerAntesDeDibujar() {
        // nada ??
    }
    
    private void hacerDespuesDeDibujar() {
        /* inicializo combo de sexos */
        listaSexos = servicioEstadisticas.obtenerTodosSexos();
        Sexo s = new Sexo();
        s.setId(-1L);
        s.setNombre("Ambos");
        listaSexos.add(0, s);
        comboboxSexo.setModel(new ListModelList<>(listaSexos));
        
        /* inicializo combos de edades */
        /*listaEdades = new ArrayList<>();
        for (int i = 0; i <= 130; i++) {
            listaEdades.add(String.valueOf(i));
        }
        comboboxEdadDesde.setModel(new ListModelList<>(listaEdades));
        comboboxEdadHasta.setModel(new ListModelList<>(listaEdades));*/
        
        listaGruposEtarios = servicioEstadisticas.obtenerTodosGruposEtarios();
        comboboxGrupoEtario.setModel(new ListModelList<>(listaGruposEtarios));
        
        /* inicializo combos de años */
        int anioMinimo = servicioEstadisticas.obtenerAnioMinimoElementos();
        int anioActual = servicioEstadisticas.obtenerAnioActual();
        
        listaAnios = new ArrayList<>();
        for (int i = anioMinimo; i <= anioActual; i++) {
            listaAnios.add(String.valueOf(i));
        }
        
        comboboxAnioDesde.setModel(new ListModelList<>(listaAnios));
        comboboxAnioHasta.setModel(new ListModelList<>(listaAnios));
        
        /* inicializo combos de meses */
        listaMeses = servicioEstadisticas.obtenerMeses();
        
        comboboxMesDesde.setModel(new ListModelList<>(listaMeses));
        comboboxMesHasta.setModel(new ListModelList<>(listaMeses));
    }
    
    @Listen("onClick = #botonCalcular")
    public void clickBotonCalcular() {
        Sexo sexoSeleccionado;
        int edadDesde;
        int edadHasta;
        int anioDesde;
        int anioHasta;
        int mesDesde;
        int mesHasta;
        
        if (validaElecciones() && validaRangos()) {
            int indiceSexo = comboboxSexo.getSelectedIndex();
            if (indiceSexo <= 0) {
                sexoSeleccionado = null;
            } else {
                sexoSeleccionado = listaSexos.get(indiceSexo);
            }
            edadDesde = listaGruposEtarios.get(comboboxGrupoEtario.getSelectedIndex()).getEdadMinima();
            edadHasta = listaGruposEtarios.get(comboboxGrupoEtario.getSelectedIndex()).getEdadMaxima();
            anioDesde = Integer.valueOf((String) comboboxAnioDesde.getSelectedItem().getValue() );
            anioHasta = Integer.valueOf((String) comboboxAnioHasta.getSelectedItem().getValue() );
            mesDesde = comboboxMesDesde.getSelectedIndex();
            mesHasta = comboboxMesHasta.getSelectedIndex();
            
            Date fechaDesde = crearFechaPrimerDia(anioDesde, mesDesde);
            Date fechaHasta = crearFechaUltimoDia(anioHasta, mesHasta);
            
            cargarDatos(sexoSeleccionado, fechaDesde, fechaHasta, edadDesde, edadHasta);
        }
    }
    
    private Date crearFechaPrimerDia(int anioDesde, int mesDesde) {
        GregorianCalendar calendar = new GregorianCalendar();
        calendar.clear(); // para que no haga quilombo con febrero (28 dias)
        calendar.set(Calendar.YEAR, anioDesde);
        calendar.set(Calendar.MONTH, mesDesde);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
        return calendar.getTime();
    }
    
    private Date crearFechaUltimoDia(int anioHasta, int mesHasta) {
        GregorianCalendar calendar = new GregorianCalendar();
        calendar.clear(); // para que no haga quilombo con febrero (28 dias)
        calendar.set(Calendar.YEAR, anioHasta);
        calendar.set(Calendar.MONTH, mesHasta);
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        return calendar.getTime();
    }
    
    private void cargarDatos( 
            Sexo sexo,
            Date fechaDesde, Date fechaHasta,
            int edadDesde, int edadHasta
    ) {
        
        GregorianCalendar calendarInicial = new GregorianCalendar();
        calendarInicial.setTime(fechaDesde);
        
        GregorianCalendar calendarFinal = new GregorianCalendar();
        calendarFinal.setTime(fechaHasta);
        
        int diferenciaAnios = calendarFinal.get(Calendar.YEAR) - calendarInicial.get(Calendar.YEAR);
        int diferenciaMeses = (diferenciaAnios * 12) + ( calendarFinal.get(Calendar.MONTH) - calendarInicial.get(Calendar.MONTH) );

        Double dato;
        String nombreMes;
        CategoryModel modelo = new DefaultCategoryModel();

        for (int i = 0; i <= diferenciaMeses; i++) {
            nombreMes = obtenerMes(fechaDesde);
            dato = servicioEstadisticas.obtenerBajasSobreTotalEnFechaEdadesSexo(sexo, fechaDesde, edadDesde, edadHasta);
            modelo.setValue("Indice", nombreMes, dato);
            fechaDesde = proximoMes(fechaDesde);
        }
        
        if (ventanaAnterior != null) {
            ventanaDetalles.removeChild(ventanaAnterior);
        }
        Map<String, Object> argumentos = new HashMap<>();
        argumentos.put("modelo",modelo);
        ventanaAnterior = (Window) Executions.createComponents("graficoMortalidad.zul", null, argumentos);
        ventanaDetalles.appendChild(ventanaAnterior);
    }
    
    private String obtenerMes(Date fecha) {
        GregorianCalendar calendar = new GregorianCalendar();
        calendar.setTime(fecha);
        
        String devolver = "";
        
        int elMes = calendar.get(Calendar.MONTH);
        switch (elMes) {
            case Calendar.JANUARY:
                devolver += "ene";
                break;
            case Calendar.FEBRUARY:
                devolver += "feb";
                break;
            case Calendar.MARCH:
                devolver += "mar";
                break;
            case Calendar.APRIL:
                devolver += "abr";
                break;
            case Calendar.MAY:
                devolver += "may";
                break;
            case Calendar.JUNE:
                devolver += "jun";
                break;
            case Calendar.JULY:
                devolver += "jul";
                break;
            case Calendar.AUGUST:
                devolver += "ago";
                break;
            case Calendar.SEPTEMBER:
                devolver += "sep";
                break;
            case Calendar.OCTOBER:
                devolver += "oct";
                break;
            case Calendar.NOVEMBER:
                devolver += "nov";
                break;
            case Calendar.DECEMBER:
                devolver += "dic";
                break;
        }
        int elAnio = calendar.get(Calendar.YEAR);
        devolver += " ´" + elAnio;
        return devolver;
    }
    
    private Date proximoMes(Date fecha) {
        GregorianCalendar calendar = new GregorianCalendar();
        calendar.setTime(fecha);
        
        int mes = calendar.get(Calendar.MONTH);
        if (mes == Calendar.DECEMBER) { // si es el ultimo mes...
            calendar.set(Calendar.MONTH, calendar.getMinimum(Calendar.MONTH)); // seteo mes minimo
            calendar.set(Calendar.YEAR, calendar.get(Calendar.YEAR) + 1); // seteo proximo año
        } else { // sino...
            calendar.set(Calendar.MONTH, calendar.get(Calendar.MONTH) + 1);
        }
        return calendar.getTime();
    }
    
    private boolean validaElecciones() {
        // si no valida, muestra cartel y devuelve false
        /*if (comboboxEdadDesde.getSelectedIndex() < 0 ) {
            Messagebox.show("Seleccione la lista desplegable Edad Desde");
            return false;
        }
        if (comboboxEdadHasta.getSelectedIndex() < 0 ) {
            Messagebox.show("Seleccione la lista desplegable Edad Hasta");
            return false;
        }*/
        if (comboboxGrupoEtario.getSelectedIndex() < 0) {
            Messagebox.show("Seleccione un Grupo Etario");
            return false;
        }
        if (comboboxAnioDesde.getSelectedIndex() < 0 ) {
            Messagebox.show("Seleccione la lista desplegable Año Desde");
            return false;
        }
        if (comboboxAnioHasta.getSelectedIndex() < 0 ) {
            Messagebox.show("Seleccione la lista desplegable Año Hasta");
            return false;
        }
        if (comboboxMesDesde.getSelectedIndex() < 0 ) {
            Messagebox.show("Seleccione la lista desplegable Mes Desde");
            return false;
        }
        if (comboboxMesHasta.getSelectedIndex() < 0 ) {
            Messagebox.show("Seleccione la lista desplegable Mes Hasta");
            return false;
        }
        return true;
    }
    
    private boolean validaRangos() {
        if (comboboxAnioDesde.getSelectedIndex() < comboboxAnioHasta.getSelectedIndex()) {
            return true;
        }
        if (comboboxAnioDesde.getSelectedIndex() == comboboxAnioHasta.getSelectedIndex()) {
            if (comboboxMesDesde.getSelectedIndex() <= comboboxMesHasta.getSelectedIndex()) {
                return true;
            } else {
                Messagebox.show("El Mes Desde debe ser menor o igual (<=) que el Mes Hasta");
                return false;
            }
        } else {
            Messagebox.show("El Año Desde debe ser menor o igual (<=) que el Año Hasta");
            return false;
        }
    }
}
